//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Reflection;
using OpenLS.Spreadsheet.Functions;
using OpenLS.Spreadsheet.Extensibility;

namespace OpenLS.Spreadsheet
{
    public class AddIn
    {
        public AddIn(Assembly assembly)
        {
            this._assembly = assembly;
            foreach (AddInLocalizerAttribute a in assembly.GetCustomAttributes(typeof (AddInLocalizerAttribute), false))
            {
                Localizer = a.Localizer;
            }
            //if (!addInFunctions.ContainsKey("IF"))
              //  addInFunctions.Add("IF", new IfFunction()); //\\
            foreach (Type t in assembly.GetTypes())
            {
                if (t.GetCustomAttributes(typeof(AddInFunctionsAttribute), false).Length > 0)
                {
                    foreach (MethodInfo m in t.GetMethods(BindingFlags.Public | BindingFlags.Static))
                    {
                        _addInFunctions.Add(GetFunctionName(m), new AddInFunction(m, Localizer, this));
                    }
                }
            }
            if (Localizer != null)
            {
                Localizer.Initialize(_addInFunctions.Keys);
            }
        }

        internal Assembly Assembly
        {
            get { return _assembly; }
        }

        static string GetFunctionName (MethodInfo methodInfo)
        {
            foreach (var customAttribute in methodInfo.GetCustomAttributes(typeof (AddInFunctionAttribute),false))
            {
                var a = (AddInFunctionAttribute) customAttribute;
                if (a.Name != null)
                    return a.Name.ToUpper();
            }
            return methodInfo.Name.ToUpper();
        }
        internal readonly IFunctionLocalizer Localizer;


        readonly Dictionary<string, Function> _addInFunctions = new Dictionary<string, Function>();
        private Assembly _assembly;

        internal bool TryGetFunction(string name, out Function result)
        {
            return _addInFunctions.TryGetValue(name, out result);
        }

        ///<summary>
        ///</summary>
        ///<returns></returns>
        public IEnumerable<AddInFunction> GetFunctions()
        {
            foreach (AddInFunction f in _addInFunctions.Values)
                yield return f;
        }

        internal Function GetFunction(string upperName, bool localized)
        {
            if (localized && Localizer != null)
                upperName = Localizer.GetGlobalName(upperName);
            return GetFunction(upperName);

        }

        private Function GetFunction(string upperName)
        {
            Function result;
            if (_addInFunctions.TryGetValue(upperName, out result))
                return result;
            return null;
        }
    }
}
